<?php
namespace App\Server;



class WeChatService
{
    private $appID;
    private $appSecret;

    private $access_token;

    public $weChatApiUrl = [

            // 获取公众号应用(小程序，小游戏，公众服务号) 开发的accessToken
        'getAccessOpenid' => "https://api.weixin.qq.com/sns/jscode2session",
        'getAccessToken' => "https://api.weixin.qq.com/cgi-bin/token",
        'getWebViewCode' => "https://open.weixin.qq.com/connect/oauth2/authorize",
        'getWebViewAccessToken' => 'https://api.weixin.qq.com/sns/oauth2/access_token',
        'getWebViewUser' => 'https://api.weixin.qq.com/sns/userinfo',
    ];


    public function __construct()
    {
        $this->appID = '';
        $this->appSecret = '';

        $this->access_token = $this->getRedisAccessToken();
    }


    /**
     * 根据code 获取openid
     * @param $code
     * @return bool|mixed|string
     */
    public function getAccessOpenidFromCode($code)
    {
        if (empty($code)) {
            return null;
        }
        $url = $this->weChatApiUrl['getAccessOpenid'];
        $params = [
            'appid' => $this->appID,
            'secret' => $this->appSecret,
            'js_code' => $code,
            'grant_type' => 'authorization_code',
        ];

        $url = $url. '?' .http_build_query($params);

        $response = http_get($url, $params);
        $response = json_decode($response, true);
        if (!empty($response['errcode'])) {
            log_err('查询用户openid出错:', to_json($response));
            return null;
        }
        return $response;
    }


    /**
     *  获取accessToken  这里获取的是公众号开发的accessToken ,比如在支付时使用
     * @return bool
     */
    public function getAccessToken()
    {
        if (!empty($this->access_token)) {
            return $this->access_token;
        }

        $url = $this->weChatApiUrl['getAccessToken'];
        $params = [
            'appid' => $this->appID,
            'secret' => $this->appSecret,
            'grant_type' => 'client_credential',
        ];

        $url = $url. '?' .http_build_query($params);

        $response = http_get($url, $params);
        $response = to_arr($response);

        if (!empty($response['errcode'])) {
            return null;
        }

        $response['expires_at'] = time() + $response['expires_in'];
        $response['created_at'] = time();

        app('redis')->set('fjmj_wechat_access_token', to_json($response));

        return $response['access_token'];
    }


    /**
     * 微信js登录 【用户同意授权，获取code】回调
     * @param $id
     * @param string $state
     * @param string $scope
     * @return string
     */
    public function getWebViewCode($id, $state = '', $scope = 'snsapi_userinfo')
    {
        $url = $this->weChatApiUrl['getWebViewCode'];
        $params = [
            'appid' => $this->appID,
            'redirect_uri' => url('/') . '/play-game/' . $id,
            'response_type' => 'code',
            'scope' => $scope,    //'snsapi_userinfo 会提示文字 / snsapi_base' 无感知,  ps: 获取的信息会不一样
            'state' => $state,      // 这里的状态值会在回调中显示出来
        ];
        $query = http_build_query($params);
        return $url . '?' . $query . "#wechat_redirect";
    }

    /**
     * 根据code 获取openid
     * @param $code
     * @return bool|mixed|string
     */
    public function getWebViewAccessToken($code)
    {
        if (empty($code)) {
            return false;
        }
        $url = $this->weChatApiUrl['getWebViewAccessToken'];
        $params = [
            'appid' => $this->appID,
            'secret' => $this->appSecret,
            'code' => $code,
            'grant_type' => 'authorization_code',
        ];
        $response = http_request_get($url, $params);
        $response = json_decode($response, true);
        if (!empty($response['errcode'])) {
            return false;
        }
        return $response;
    }


    public function getUserFromOpenId($access_token, $openid)
    {
        $url = $this->weChatApiUrl['getWebViewUser'];
        $params = [
            'access_token' => $access_token,
            'openid' => $openid,
            'lang' => 'zh_CN'
        ];
        $params = http_build_query($params);
        $response = http_get($url.'?'.$params);
        $response = to_arr($response);
        return $response;
    }



    /***
     * @return string|null
     */
    private function getRedisAccessToken()
    {
        $access_token = redis()->get('fjmj_wechat_access_token');

        if (empty($access_token)) {
            return null;
        }

        $access_token = to_arr($access_token);

        if ($access_token['expires_at'] < (time() - 300)) {
            return null;
        }

        return $access_token['access_token'];
    }

}
